#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#include <time.h>
// sprintf/sscanf不安全。格式输入输出。跟printf类似。只是输出/输入到字符串中。
// snprintf更安全。不用担心越界问题。输出末尾自动补结束符'\0'. 预期长度大于指定长度时，末尾也会补'\0'.
// vsnprintf自定义格式输出。可以实现不定长度参数输入。可以自己实现snprintf

// va_list需要头文件<stdarg.h>
// c99才支持vsnprintf。
static int mysnprintf(char *out, int outsize, const char *format, ...)
{
    va_list args;
    if(!out)
    {
        printf("[%s,%s,%d]\n", __FILE__, __func__, __LINE__);
        return -1;
    }
    va_start(args, format);
    size_t tmplen = vsnprintf(out, outsize, format, args);
    va_end(args);
    if (tmplen > outsize)
    {
        printf("[%s,%s,%d]data is over:%d,%d\n", __FILE__, __func__, __LINE__, (int)tmplen, (int)outsize);
        tmplen = outsize;
    }
    return tmplen;
}


int main(int argc, char **argv)
{
#define MY_CHECK_DATA_SIZE 32
    char tmpbuffer[MY_CHECK_DATA_SIZE];
    time_t tmptime = time(NULL);
    const char *tmpFixedStr = "my fixed string";
    int tmpSnprtLen;
    memset(tmpbuffer, 1, sizeof(tmpbuffer));
    tmpSnprtLen = snprintf(tmpbuffer, sizeof(tmpbuffer), "data1, time now = %lu, value = %s", tmptime, tmpFixedStr);
    printf("[%s,%s,%d]data1 expect:%d,real:%d\n", __FILE__, __func__, __LINE__, tmpSnprtLen, (int)strlen(tmpbuffer));
    printf("[%s,%s,%d]%s\n", __FILE__, __func__, __LINE__, tmpbuffer);
    memset(tmpbuffer, 1, sizeof(tmpbuffer));
    tmpSnprtLen = snprintf(tmpbuffer, sizeof(tmpbuffer), "data2: %s", tmpFixedStr);
    printf("[%s,%s,%d]data2 expect:%d,real:%d\n", __FILE__, __func__, __LINE__, tmpSnprtLen, (int)strlen(tmpbuffer));
    printf("[%s,%s,%d]%s\n", __FILE__, __func__, __LINE__, tmpbuffer);
    mysnprintf(tmpbuffer, sizeof(tmpbuffer), "data3, time now = %lu, value = %s", tmptime, tmpFixedStr);
    printf("[%s,%s,%d]%s\n", __FILE__, __func__, __LINE__, tmpbuffer);
    return 1;
}
